﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#nullable disable

using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Drawing;
using System.Drawing.Design;
using System.Globalization;
using System.Windows.Forms.Design.Behavior;

namespace System.Windows.Forms.Design;

/// <summary>
///  Designer for the ToolStrip class.
/// </summary>
internal class ToolStripDesigner : ControlDesigner
{
    private const int GLYPHBORDER = 2;
    internal static Point s_lastCursorPosition = Point.Empty; // remembers last cursorPosition;
    internal static bool s_autoAddNewItems = true; // true to force newly created items to be added to the currently selected strip.
    internal static ToolStripItem s_dragItem; // this is used in overflow to know current item selected while drag, so that we can get the drop-index.
    internal static bool s_shiftState; // maintains the shift state used of invalidation. Disable C# compiler warning #0414: field assigned unused value
#pragma warning disable 0414
    internal static bool s_editTemplateNode; // this is used in selection changed so that unnecessary redraw is not required.
#pragma warning restore 0414
    private DesignerToolStripControlHost _editorNode; // new editorNode
    private ToolStripEditorManager _editManager; // newly added editor manager ...
    private ToolStrip _miniToolStrip; // the toolStrip that hosts the "New Template Node" button
    private DesignerTransaction _insertMenuItemTransaction; // There Should be one and only one Pending insertTransaction.
    private Rectangle _dragBoxFromMouseDown = Rectangle.Empty; // Needed to Store the DRAGDROP Rect from the ToolStripItemBehavior.
    private int _indexOfItemUnderMouseToDrag = -1; // defaulted to invalid index and will be set by the behavior.
    private ToolStripTemplateNode _tn; // templateNode
    private ISelectionService _selectionService; // cached selection service.
    private uint _editingCollection; // non-zero if the collection editor is up for this ToolStrip or a child of it.
    private DesignerTransaction _pendingTransaction; // our transaction for adding/removing items.
    private bool _addingItem; // true if we are expecting to be notified of adding a ToolStripItem to the designer.
    private Rectangle _boundsToInvalidate = Rectangle.Empty; // Bounds to Invalidate if a DropDownItem is Deleted
    private bool _currentVisible = true; // Change Visibility
    private ToolStripActionList _actionLists; // Action List on Chrome...
    private ToolStripAdornerWindowService _toolStripAdornerWindowService; // Add the Adorner Service for OverFlow DropDown...
    private IDesignerHost _host; // get private copy of the DesignerHost
    private IComponentChangeService _componentChangeService;
    private UndoEngine _undoEngine;
    private bool _undoingCalled;
    private IToolboxService _toolboxService;
    private ContextMenuStrip _toolStripContextMenu;
    private bool _toolStripSelected;
    private bool _cacheItems; // ToolStripDesigner would cache items for the MenuItem when dropdown is changed.
    private ArrayList _items; // cached Items.
    private bool _disposed;
    private DesignerTransaction _newItemTransaction;
    private bool _fireSyncSelection; // fires SyncSelection when we toggle the items visibility to add the glyphs after the item gets visible.
    private ToolStripKeyboardHandlingService _keyboardHandlingService;
    private bool _parentNotVisible; // sync the parent visibility (used for ToolStripPanels)
    private bool _dontCloseOverflow; // When an item is added to the ToolStrip through the templateNode which is on the Overflow; we should not close the overflow (to avoid flicker)
    private bool _addingDummyItem; // When the dummyItem is added the toolStrip might resize (as in the Vertical Layouts). In this case we don't want the Resize to cause SyncSelection and Layouts.

    /// <summary>
    ///  Adds designer actions to the ActionLists collection.
    /// </summary>
    public override DesignerActionListCollection ActionLists
    {
        get
        {
            DesignerActionListCollection actionLists = new();
            actionLists.AddRange(base.ActionLists);
            _actionLists ??= new ToolStripActionList(this);

            actionLists.Add(_actionLists);

            // First add the verbs for this component there...
            DesignerVerbCollection verbs = Verbs;
            if (verbs is not null && verbs.Count != 0)
            {
                DesignerVerb[] verbsArray = new DesignerVerb[verbs.Count];
                verbs.CopyTo(verbsArray, 0);
                actionLists.Add(new DesignerActionVerbList(verbsArray));
            }

            return actionLists;
        }
    }

    /// <summary>
    ///  Compute the rect for the "Add New Item" button.
    /// </summary>
    private Rectangle AddItemRect
    {
        get
        {
            Rectangle rect = default;
            if (_miniToolStrip is null)
            {
                return rect;
            }

            rect = _miniToolStrip.Bounds;
            return rect;
        }
    }

    /// <summary>
    ///  Accessor for Shadow Property for AllowDrop.
    /// </summary>
    private bool AllowDrop
    {
        get => (bool)ShadowProperties[nameof(AllowDrop)];
        set
        {
            if (value && AllowItemReorder)
            {
                throw new ArgumentException(SR.ToolStripAllowItemReorderAndAllowDropCannotBeSetToTrue);
            }

            ShadowProperties[nameof(AllowDrop)] = value;
        }
    }

    /// <summary>
    ///  Accessor for Shadow Property for AllowItemReorder.
    /// </summary>
    private bool AllowItemReorder
    {
        get => (bool)ShadowProperties[nameof(AllowItemReorder)];
        set
        {
            if (value && AllowDrop)
            {
                throw new ArgumentException(SR.ToolStripAllowItemReorderAndAllowDropCannotBeSetToTrue);
            }

            ShadowProperties[nameof(AllowItemReorder)] = value;
        }
    }

    /// <summary>
    ///  The ToolStripItems are the associated components. We want those to come with in any cut, copy operations.
    /// </summary>
    public override ICollection AssociatedComponents
    {
        get
        {
            ArrayList items = [];
            foreach (ToolStripItem item in ToolStrip.Items)
            {
                if (item is not DesignerToolStripControlHost)
                {
                    items.Add(item);
                }
            }

            return items;
        }
    }

    /// <summary>
    ///  CacheItems is set to TRUE by the ToolStripMenuItemDesigner, when the Transaction of setting
    ///  the DropDown property is undone. In this case the Undo adds the original items to
    ///  the Main MenuStripDesigners Items collection and later are moved to to the appropriate ToolStripMenuItem.
    /// </summary>
    public bool CacheItems
    {
        get => _cacheItems;
        set => _cacheItems = value;
    }

    /// <summary>
    ///  False if were inherited and can't be modified.
    /// </summary>
    private bool CanAddItems
    {
        get
        {
            // Make sure the component is not being inherited -- we can't delete these!
            InheritanceAttribute inheritanceAttribute =
                (InheritanceAttribute)TypeDescriptor.GetAttributes(ToolStrip)[typeof(InheritanceAttribute)];
            return inheritanceAttribute is null || inheritanceAttribute.InheritanceLevel == InheritanceLevel.NotInherited;
        }
    }

    /// <summary>
    ///  This boolean indicates whether the Control will allow SnapLines to be shown when any other targetControl
    ///  is dragged on the design surface. This is true by default.
    /// </summary>
    internal override bool ControlSupportsSnaplines => ToolStrip.Parent is not ToolStripPanel;

    /// <summary>
    ///  DesignerContextMenu that is shown on the ToolStrip/MenuStrip/StatusStrip.
    /// </summary>
    private ContextMenuStrip DesignerContextMenu
    {
        get
        {
            _toolStripContextMenu ??= new BaseContextMenuStrip(ToolStrip.Site)
            {
                Text = "CustomContextMenu"
            };

            return _toolStripContextMenu;
        }
    }

    /// <summary>
    ///  Used by ToolStripTemplateNode. When the ToolStrip gains selection the Overflow is closed.
    ///  But when an item is added through the TemplateNode which itself is on the Overflow, we should not close
    ///  the Overflow as this caused weird artifacts and flicker. Hence this boolean property.
    /// </summary>
    public bool DontCloseOverflow
    {
        get => _dontCloseOverflow;
        set => _dontCloseOverflow = value;
    }

    /// <summary>
    ///  Since the Item glyphs are recreated on the SelectionChanged, we need to cache in the "MouseDown"
    ///  while the item Drag-Drop operation.
    /// </summary>
    public Rectangle DragBoxFromMouseDown
    {
        get => _dragBoxFromMouseDown;
        set => _dragBoxFromMouseDown = value;
    }

    /// <summary>
    ///  Set by the ToolStripItemCollectionEditor when it's launched for this ToolStrip so we won't pick up
    ///  it's items when added. We count this so that we can deal with nesting's.
    /// </summary>
    internal bool EditingCollection
    {
        get => _editingCollection != 0;
        set
        {
            if (value)
            {
                _editingCollection++;
            }
            else
            {
                _editingCollection--;
            }
        }
    }

    /// <summary>
    ///  EditManager for the ToolStrip Designer. This EditorManager controls the InSitu Editing.
    /// </summary>
    public ToolStripEditorManager EditManager
    {
        get => _editManager;
    }

    /// <summary>
    ///  The TemplateNode. This is the object that actually creates miniToolStrip and manages InSitu editing.
    /// </summary>
    internal ToolStripTemplateNode Editor
    {
        get => _tn;
    }

    /// <summary>
    ///  This is the ToolStripControlHost that hosts the ToolStripTemplateNode's miniToolStrip.
    /// </summary>
    public DesignerToolStripControlHost EditorNode
    {
        get => _editorNode;
    }

    /// <summary>
    ///  This is the ToolStripTemplateNode's miniToolStrip.
    /// </summary>
    internal ToolStrip EditorToolStrip
    {
        get => _miniToolStrip;
        set
        {
            _miniToolStrip = value;
            _miniToolStrip.Parent = ToolStrip;
            LayoutToolStrip();
        }
    }

    /// <summary>
    ///  This will be set through ToolStripItemDesigner.SetItemVisible( ) if we find there is atleast one time
    ///  that toggled from Visible==false to Visible==true In such a case we need to
    ///  call BehaviorService.SyncSelection( ) to update the glyphs.
    /// </summary>
    public bool FireSyncSelection
    {
        get => _fireSyncSelection;
        set => _fireSyncSelection = value;
    }

    /// <summary>
    ///  Since the Item glyphs are recreated on the SelectionChanged, we need to cache in the "index" of last MouseDown
    ///  while the item Drag-Drop operation.
    /// </summary>
    public int IndexOfItemUnderMouseToDrag
    {
        get => _indexOfItemUnderMouseToDrag;
        set => _indexOfItemUnderMouseToDrag = value;
    }

    /// <summary>
    ///  ToolStrips if inherited act as ReadOnly.
    /// </summary>
    protected override InheritanceAttribute InheritanceAttribute
    {
        get
        {
            return base.InheritanceAttribute == InheritanceAttribute.Inherited
                ? InheritanceAttribute.InheritedReadOnly
                : base.InheritanceAttribute;
        }
    }

    /// <summary>
    ///  This is the insert Transaction. Now insert can happen at Main Menu level or the DropDown Level.
    ///  This transaction is used to keep both in sync.
    /// </summary>
    public DesignerTransaction InsertTransaction
    {
        get => _insertMenuItemTransaction;
        set => _insertMenuItemTransaction = value;
    }

    /// <summary>
    ///  Checks if there is a selection of the ToolStrip or one of it's items.
    /// </summary>
    private bool IsToolStripOrItemSelected => _toolStripSelected;

    /// <summary>
    ///  CacheItems is set to TRUE by the ToolStripMenuItemDesigner, when the Transaction of setting
    ///  the DropDown property is undone. In this case the Undo adds the original items to the
    ///  Main MenuStripDesigners Items collection and later are moved to to the appropriate ToolStripMenuItem.
    ///  This is the Items Collection.
    /// </summary>
    public ArrayList Items
    {
        get
        {
            _items ??= [];

            return _items;
        }
    }

    /// <summary>
    ///  This is the new item Transaction. This is used when the InSitu editor adds new Item.
    /// </summary>
    public DesignerTransaction NewItemTransaction
    {
        get => _newItemTransaction;
        set => _newItemTransaction = value;
    }

    /// <summary>
    ///  Compute the rect for the "OverFlow" button.
    /// </summary>
    private Rectangle OverFlowButtonRect
    {
        get
        {
            Rectangle rect = default;
            return ToolStrip.OverflowButton.Visible ? ToolStrip.OverflowButton.Bounds : rect;
        }
    }

    /// <summary>
    ///  Get and cache the selection service
    /// </summary>
    internal ISelectionService SelectionService => _selectionService ??= GetService<ISelectionService>();

    public bool SupportEditing =>
        GetService<DesignerOptionService>() is not WindowsFormsDesignerOptionService dos
            || dos.CompatibilityOptions.EnableInSituEditing;

    /// <summary>
    ///  Handy way of getting our ToolStrip
    /// </summary>
    protected ToolStrip ToolStrip => (ToolStrip)Component;

    /// <summary>
    ///  Get and cache the toolStripKeyBoard service
    /// </summary>
    private ToolStripKeyboardHandlingService KeyboardHandlingService
    {
        get
        {
            if (_keyboardHandlingService is null)
            {
                // Add the EditService so that the ToolStrip can do its own Tab and Keyboard Handling
                _keyboardHandlingService = GetService<ToolStripKeyboardHandlingService>();
                _keyboardHandlingService ??= new ToolStripKeyboardHandlingService(Component.Site);
            }

            return _keyboardHandlingService;
        }
    }

    /// <summary>
    ///  There are certain containers (like ToolStrip) that require PerformLayout to be serialized in the code gen.
    /// </summary>
    internal override bool SerializePerformLayout => true;

    /// <summary>
    ///  Un - ShadowProperty.
    /// </summary>
    internal bool Visible
    {
        get => _currentVisible;
        set
        {
            _currentVisible = value;
            // If the user has set the Visible to false, sync the controls visible property.
            if (ToolStrip.Visible != value && !SelectionService.GetComponentSelected(ToolStrip))
            {
                Control.Visible = value;
            }
        }
    }

    /// <summary>
    ///  This will add BodyGlyphs for the Items on the OverFlow. Since ToolStripItems
    ///  are component we have to manage Adding and Deleting the glyphs ourSelves.
    /// </summary>
    private void AddBodyGlyphsForOverflow()
    {
        // now walk the ToolStrip and add glyphs for each of it's children
        foreach (ToolStripItem item in ToolStrip.Items)
        {
            if (item is DesignerToolStripControlHost)
            {
                continue;
            }

            // make sure it's on the Overflow...
            if (item.Placement == ToolStripItemPlacement.Overflow)
            {
                AddItemBodyGlyph(item);
            }
        }
    }

    /// <summary>
    ///  This will add BodyGlyphs for the Items on the OverFlow. Since ToolStripItems are component we have
    ///  to manage Adding and Deleting the glyphs ourSelves. Called by AddBodyGlyphsForOverflow().
    /// </summary>
    private void AddItemBodyGlyph(ToolStripItem item)
    {
        if (item is not null)
        {
            ToolStripItemDesigner dropDownItemDesigner = (ToolStripItemDesigner)_host.GetDesigner(item);
            if (dropDownItemDesigner is not null)
            {
                Rectangle bounds = dropDownItemDesigner.GetGlyphBounds();
                Behavior.Behavior toolStripBehavior = new ToolStripItemBehavior();
                // Initialize Glyph
                ToolStripItemGlyph bodyGlyphDropDownItem = new(item, dropDownItemDesigner, bounds, toolStripBehavior);
                // Set the glyph for the item .. so that we can remove it later....
                dropDownItemDesigner._bodyGlyph = bodyGlyphDropDownItem;
                // Add ItemGlyph to the Collection
                _toolStripAdornerWindowService?.DropDownAdorner.Glyphs.Add(bodyGlyphDropDownItem);
            }
        }
    }

    /// <summary>
    ///  Fired when a new item is chosen from the AddItems menu from the Template Node.
    /// </summary>
    private ToolStripItem AddNewItem(Type t)
    {
        Debug.Assert(_host is not null, "Why didn't we get a designer host?");
        NewItemTransaction = _host.CreateTransaction(SR.ToolStripCreatingNewItemTransaction);
        IComponent component = null;
        try
        {
            _addingItem = true;
            // Suspend the Layout as we are about to add Item to the ToolStrip
            ToolStrip.SuspendLayout();
            ToolStripItemDesigner designer = null;
            try
            {
                // The code in ComponentAdded will actually get the add done.
                // This should be inside the try finally because it could throw an exception and
                // keep the toolstrip in SuspendLayout mode
                component = _host.CreateComponent(t);
                designer = _host.GetDesigner(component) as ToolStripItemDesigner;
                designer.InternalCreate = true;
                designer?.InitializeNewComponent(null);
            }
            finally
            {
                designer?.InternalCreate = false;

                // Resume the Layout as we are about to add Item to the ToolStrip
                ToolStrip.ResumeLayout();
            }
        }
        catch (Exception e)
        {
            if (NewItemTransaction is not null)
            {
                NewItemTransaction.Cancel();
                NewItemTransaction = null;
            }

            // Throw the exception unless it's a canceled checkout
            if ((!(e is CheckoutException checkoutException)) || (!checkoutException.Equals(CheckoutException.Canceled)))
            {
                throw;
            }
        }
        finally
        {
            _addingItem = false;
        }

        return component as ToolStripItem;
    }

    // Standard 'catch all - rethrow critical' exception pattern
    internal ToolStripItem AddNewItem(Type t, string text, bool enterKeyPressed, bool tabKeyPressed)
    {
        Debug.Assert(_host is not null, "Why didn't we get a designer host?");
        Debug.Assert(_pendingTransaction is null, "Adding item with pending transaction?");
        DesignerTransaction outerTransaction = _host.CreateTransaction(string.Format(SR.ToolStripAddingItem, t.Name));
        ToolStripItem item = null;
        try
        {
            _addingItem = true;
            // Suspend the Layout as we are about to add Item to the ToolStrip
            ToolStrip.SuspendLayout();
            // The code in ComponentAdded will actually get the add done.
            IComponent component = _host.CreateComponent(t, NameFromText(text, t, Component.Site));
            ToolStripItemDesigner designer = _host.GetDesigner(component) as ToolStripItemDesigner;
            try
            {
                // ToolStripItem designer tries to set the TEXT for the item in the InitializeNewComponent().
                // But since we are create item thru InSitu .. we shouldn't do this.
                // Also we shouldn't set the TEXT if we are creating a dummyItem.
                if (!string.IsNullOrEmpty(text))
                {
                    designer.InternalCreate = true;
                }

                designer?.InitializeNewComponent(null);
            }
            finally
            {
                designer.InternalCreate = false;
            }

            // Set the Text and Image..
            item = component as ToolStripItem;
            if (item is not null)
            {
                PropertyDescriptor textProperty = TypeDescriptor.GetProperties(item)[nameof(Text)];
                Debug.Assert(textProperty is not null, "Could not find 'Text' property in ToolStripItem.");
                if (textProperty is not null && !string.IsNullOrEmpty(text))
                {
                    textProperty.SetValue(item, text);
                }

                // Set the Image property and DisplayStyle...
                if (item is ToolStripButton or ToolStripSplitButton or ToolStripDropDownButton)
                {
                    Image image = null;
                    try
                    {
                        image = new Icon(typeof(ToolStripButton), "blank").ToBitmap();
                    }
                    catch (Exception e) when (!e.IsCriticalException())
                    {
                    }

                    PropertyDescriptor imageProperty = TypeDescriptor.GetProperties(item)[nameof(Image)];
                    Debug.Assert(imageProperty is not null, "Could not find 'Image' property in ToolStripItem.");
                    if (imageProperty is not null && image is not null)
                    {
                        imageProperty.SetValue(item, image);
                    }

                    PropertyDescriptor displayProperty = TypeDescriptor.GetProperties(item)["DisplayStyle"];
                    Debug.Assert(displayProperty is not null, "Could not find 'DisplayStyle' property in ToolStripItem.");
                    displayProperty?.SetValue(item, ToolStripItemDisplayStyle.Image);

                    PropertyDescriptor imageTransProperty = TypeDescriptor.GetProperties(item)["ImageTransparentColor"];
                    Debug.Assert(imageTransProperty is not null, "Could not find 'DisplayStyle' property in ToolStripItem.");
                    imageTransProperty?.SetValue(item, Color.Magenta);
                }
            }

            // ResumeLayout on ToolStrip.
            ToolStrip.ResumeLayout();
            if (!tabKeyPressed)
            {
                if (enterKeyPressed)
                {
                    if (!designer.SetSelection(enterKeyPressed))
                    {
                        if (KeyboardHandlingService is not null)
                        {
                            KeyboardHandlingService.SelectedDesignerControl = _editorNode;
                            SelectionService.SetSelectedComponents(null, SelectionTypes.Replace);
                        }
                    }
                }
                else
                {
                    // Put the templateNode into non-selection mode && select the existing Item.
                    KeyboardHandlingService.SelectedDesignerControl = null;
                    SelectionService.SetSelectedComponents(new IComponent[] { item }, SelectionTypes.Replace);
                    _editorNode.RefreshSelectionGlyph();
                }
            }
            else
            {
                if (_keyboardHandlingService is not null)
                {
                    KeyboardHandlingService.SelectedDesignerControl = _editorNode;
                    SelectionService.SetSelectedComponents(null, SelectionTypes.Replace);
                }
            }

            if (designer is not null && item.Placement != ToolStripItemPlacement.Overflow)
            {
                Rectangle bounds = designer.GetGlyphBounds();
                Behavior.Behavior toolStripBehavior = new ToolStripItemBehavior();
                ToolStripItemGlyph bodyGlyphForItem = new(item, designer, bounds, toolStripBehavior);

                // Add ItemGlyph to the Collection
                GetService<SelectionManager>().BodyGlyphAdorner.Glyphs.Insert(0, bodyGlyphForItem);
            }
            else if (designer is not null && item.Placement == ToolStripItemPlacement.Overflow)
            {
                // Add Glyphs for overflow...
                RemoveBodyGlyphsForOverflow();
                AddBodyGlyphsForOverflow();
            }
        }
        catch (Exception exception)
        {
            // ResumeLayout on ToolStrip.
            ToolStrip.ResumeLayout();
            if (_pendingTransaction is not null)
            {
                _pendingTransaction.Cancel();
                _pendingTransaction = null;
            }

            if (outerTransaction is not null)
            {
                outerTransaction.Cancel();
                outerTransaction = null;
            }

            if (exception is CheckoutException checkoutEx && checkoutEx != CheckoutException.Canceled)
            {
                throw;
            }
        }
        finally
        {
            if (_pendingTransaction is not null)
            {
                _pendingTransaction.Cancel();
                _pendingTransaction = null;

                outerTransaction?.Cancel();
            }
            else
            {
                outerTransaction?.Commit();
            }

            _addingItem = false;
        }

        return item;
    }

    /// <summary>
    ///  Adds the new TemplateNode to the ToolStrip or MenuStrip.
    /// </summary>
    internal void AddNewTemplateNode()
    {
        // Setup the MINIToolStrip host.
        _tn = new ToolStripTemplateNode(Component, SR.ToolStripDesignerTemplateNodeEnterText);
        _miniToolStrip = _tn.EditorToolStrip;
        int width = _tn.EditorToolStrip.Width;
        _editorNode = new DesignerToolStripControlHost(_tn.EditorToolStrip);
        _tn.ControlHost = _editorNode;
        _editorNode.Width = width;
        ToolStrip.Items.Add(_editorNode);
        _editorNode.Visible = false;
    }

    internal void CancelPendingMenuItemTransaction()
    {
        _insertMenuItemTransaction?.Cancel();
    }

    /// <summary>
    ///  Check if the ToolStripItems are selected.
    /// </summary>
    private bool CheckIfItemSelected()
    {
        bool showToolStrip = false;
        object comp = SelectionService.PrimarySelection;
        comp ??= (IComponent)KeyboardHandlingService.SelectedDesignerControl;

        if (comp is ToolStripItem item)
        {
            if (item.Placement == ToolStripItemPlacement.Overflow && item.Owner == ToolStrip)
            {
                if (ToolStrip.CanOverflow && !ToolStrip.OverflowButton.DropDown.Visible)
                {
                    ToolStrip.OverflowButton.ShowDropDown();
                }

                showToolStrip = true;
            }
            else
            {
                if (!ItemParentIsOverflow(item))
                {
                    if (ToolStrip.OverflowButton.DropDown.Visible)
                    {
                        ToolStrip.OverflowButton.HideDropDown();
                    }
                }

                if (item.Owner == ToolStrip)
                {
                    showToolStrip = true;
                }
                else if (item is DesignerToolStripControlHost)
                {
                    if (item.IsOnDropDown && item.Placement != ToolStripItemPlacement.Overflow)
                    {
                        ToolStripDropDown dropDown = (ToolStripDropDown)((DesignerToolStripControlHost)comp).GetCurrentParent();
                        if (dropDown is not null)
                        {
                            ToolStripItem ownerItem = dropDown.OwnerItem;
                            ToolStripDropDown topmost = ToolStripItemDesigner.GetFirstDropDown((ToolStripDropDownItem)(ownerItem));
                            ToolStripItem topMostItem = (topmost is null) ? ownerItem : topmost.OwnerItem;

                            if (topMostItem is not null && topMostItem.Owner == ToolStrip)
                            {
                                showToolStrip = true;
                            }
                        }
                    }
                }
                else if (item.IsOnDropDown && item.Placement != ToolStripItemPlacement.Overflow)
                {
                    ToolStripItem parentItem = ((ToolStripDropDown)(item.Owner)).OwnerItem;
                    if (parentItem is not null)
                    {
                        ToolStripDropDown topmost = ToolStripItemDesigner.GetFirstDropDown((ToolStripDropDownItem)parentItem);
                        ToolStripItem topMostItem = (topmost is null) ? parentItem : topmost.OwnerItem;
                        if (topMostItem is not null && topMostItem.Owner == ToolStrip)
                        {
                            showToolStrip = true;
                        }
                    }
                }
            }
        }

        return showToolStrip;
    }

    /// <summary>
    ///  This is called ToolStripItemGlyph to commit the TemplateNode Edition on the Parent ToolStrip.
    /// </summary>
    internal bool Commit()
    {
        if (_tn is not null && _tn.Active)
        {
            _tn.Commit(false, false);
            _editorNode.Width = _tn.EditorToolStrip.Width;
        }
        else
        {
            if (SelectionService.PrimarySelection is ToolStripDropDownItem selectedItem)
            {
                if (_host.GetDesigner(selectedItem) is ToolStripMenuItemDesigner itemDesigner && itemDesigner.IsEditorActive)
                {
                    itemDesigner.Commit();
                    return true;
                }
            }
            else
            {
                if (KeyboardHandlingService is not null)
                {
                    if (KeyboardHandlingService.SelectedDesignerControl is ToolStripItem designerItem && designerItem.IsOnDropDown)
                    {
                        if (designerItem.GetCurrentParent() is ToolStripDropDown parent)
                        {
                            if (parent.OwnerItem is ToolStripDropDownItem ownerItem)
                            {
                                if (_host.GetDesigner(ownerItem) is ToolStripMenuItemDesigner itemDesigner && itemDesigner.IsEditorActive)
                                {
                                    itemDesigner.Commit();
                                    return true;
                                }
                            }
                        }
                    }
                    else
                    { // check for normal ToolStripItem selection ....
                        if (SelectionService.PrimarySelection is ToolStripItem toolItem)
                        {
                            ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)_host.GetDesigner(toolItem);
                            if (itemDesigner is not null && itemDesigner.IsEditorActive)
                            {
                                itemDesigner.Editor.Commit(false, false);
                                return true;
                            }
                        }
                    }
                }
            }
        }

        return false;
    }

    /// <summary>
    ///  Make sure the AddNewItem button is setup properly.
    /// </summary>
    private void Control_HandleCreated(object sender, EventArgs e)
    {
        Control.HandleCreated -= Control_HandleCreated;

        InitializeNewItemDropDown();

        // We should HOOK this event here since getting the OverFlowButton property causes
        // handle creation which we need to avoid
        // hook the designer for the OverFlow Item events..
        ToolStrip.OverflowButton.DropDown.Closing += OnOverflowDropDownClosing;
        ToolStrip.OverflowButton.DropDownOpening += OnOverFlowDropDownOpening;
        ToolStrip.OverflowButton.DropDownOpened += OnOverFlowDropDownOpened;
        ToolStrip.OverflowButton.DropDownClosed += OnOverFlowDropDownClosed;
        ToolStrip.OverflowButton.DropDown.Resize += OnOverflowDropDownResize;
        ToolStrip.OverflowButton.DropDown.Paint += OnOverFlowDropDownPaint;

        ToolStrip.Move += OnToolStripMove;
        ToolStrip.VisibleChanged += OnToolStripVisibleChanged;
        ToolStrip.ItemAdded += OnItemAdded;
    }

    /// <summary>
    ///  Fired after a component has been added. Here, we add it to the ToolStrip and select it.
    /// </summary>
    private void ComponentChangeSvc_ComponentAdded(object sender, ComponentEventArgs e)
    {
        // If another ToolStrip is getting added and we are currently selected then unselect us .. the newly added
        // toolStrip should get selected.
        if (_toolStripSelected && e.Component is ToolStrip)
        {
            _toolStripSelected = false;
        }

        try
        {
            // make sure it's one of ours and not on DropDown.
            if (e.Component is ToolStripItem newItem && _addingItem && !newItem.IsOnDropDown)
            {
                _addingItem = false;
                if (CacheItems)
                {
                    _items.Add(newItem);
                }
                else
                {
                    // Get the current count of ToolStripItems.
                    int count = ToolStrip.Items.Count;
                    // notify the designer what's changed.
                    try
                    {
                        RaiseComponentChanging(TypeDescriptor.GetProperties(Component)[nameof(Items)]);
                        if (SelectionService.PrimarySelection is ToolStripItem selectedItem)
                        {
                            // ADD at the current Selection ...
                            if (selectedItem.Owner == ToolStrip)
                            {
                                int indexToInsert = ToolStrip.Items.IndexOf(selectedItem);
                                ToolStrip.Items.Insert(indexToInsert, newItem);
                            }
                        }
                        else if (count > 0)
                        {
                            // ADD at Last but one, the last one being the TemplateNode always...
                            ToolStrip.Items.Insert(count - 1, newItem);
                        }
                        else
                        {
                            ToolStrip.Items.Add(newItem);
                        }
                    }
                    finally
                    {
                        RaiseComponentChanged(TypeDescriptor.GetProperties(Component)[nameof(Items)], null, null);
                    }
                }
            }
        }
        catch
        {
            if (_pendingTransaction is not null)
            {
                _pendingTransaction.Cancel();
                _pendingTransaction = null;
                _insertMenuItemTransaction = null;
            }
        }
        finally
        {
            if (_pendingTransaction is not null)
            {
                _pendingTransaction.Commit();
                _pendingTransaction = null;
                _insertMenuItemTransaction = null;
            }
        }
    }

    /// <summary>
    ///  Checks if the component being added is a child ToolStripItem.
    /// </summary>
    private void ComponentChangeSvc_ComponentAdding(object sender, ComponentEventArgs e)
    {
        if (KeyboardHandlingService is not null && KeyboardHandlingService.CopyInProgress)
        {
            return;
        }

        // Return if we are not the owner !!
        object selectedItem = SelectionService.PrimarySelection;
        if (selectedItem is null)
        {
            if (_keyboardHandlingService is not null)
            {
                selectedItem = KeyboardHandlingService.SelectedDesignerControl;
            }
        }

        if (selectedItem is ToolStripItem currentSel && currentSel.Owner != ToolStrip)
        {
            return;
        }

        // we'll be adding a child item if the component is a ToolStrip item and we've currently got this ToolStrip
        // or one of it's items selected. we do this so things like paste and undo automagically work.
        ToolStripItem addingItem = e.Component as ToolStripItem;
        if (addingItem is not null && addingItem.Owner is not null)
        {
            if (addingItem.Owner.Site is null)
            {
                // We are DummyItem to the ToolStrip.
                return;
            }
        }

        if (_insertMenuItemTransaction is null && s_autoAddNewItems && addingItem is not null && !_addingItem && IsToolStripOrItemSelected && !EditingCollection)
        {
            _addingItem = true;

            if (_pendingTransaction is null)
            {
                Debug.Assert(_host is not null, "Why didn't we get a designer host?");
                _insertMenuItemTransaction = _pendingTransaction = _host.CreateTransaction(SR.ToolStripDesignerTransactionAddingItem);
            }
        }
    }

    /// <summary>
    ///  Required to check if we need to show the Overflow, if any change has caused the item to go into the overflow.
    /// </summary>
    private void ComponentChangeSvc_ComponentChanged(object sender, ComponentChangedEventArgs e)
    {
        if (e.Component is ToolStripItem changingItem)
        {
            ToolStrip parent = changingItem.Owner;
            if (parent == ToolStrip && e.Member is not null && e.Member.Name == "Overflow")
            {
                ToolStripItemOverflow oldValue = (ToolStripItemOverflow)e.OldValue;
                ToolStripItemOverflow newValue = (ToolStripItemOverflow)e.NewValue;
                if (oldValue != ToolStripItemOverflow.Always && newValue == ToolStripItemOverflow.Always)
                {
                    // If now the Item falls in the Overflow .. Open the Overflow..
                    if (ToolStrip.CanOverflow && !ToolStrip.OverflowButton.DropDown.Visible)
                    {
                        ToolStrip.OverflowButton.ShowDropDown();
                    }
                }
            }
        }
    }

    /// <summary>
    ///  After a ToolStripItem is removed, remove it from the ToolStrip and select the next item.
    /// </summary>
    private void ComponentChangeSvc_ComponentRemoved(object sender, ComponentEventArgs e)
    {
        if (e.Component is ToolStripItem item && item.Owner == Component)
        {
            int itemIndex = ToolStrip.Items.IndexOf(item);
            // send notifications.
            try
            {
                if (itemIndex != -1)
                {
                    ToolStrip.Items.Remove(item);
                    RaiseComponentChanged(TypeDescriptor.GetProperties(Component)[nameof(Items)], null, null);
                }
            }
            finally
            {
                if (_pendingTransaction is not null)
                {
                    _pendingTransaction.Commit();
                    _pendingTransaction = null;
                }
            }

            // select the next item or the ToolStrip itself.
            if (ToolStrip.Items.Count > 1)
            {
                itemIndex = Math.Min(ToolStrip.Items.Count - 1, itemIndex);
                itemIndex = Math.Max(0, itemIndex);
            }
            else
            {
                itemIndex = -1;
            }

            LayoutToolStrip();

            // Reset the Glyphs if the item removed is on the OVERFLOW,
            if (item.Placement == ToolStripItemPlacement.Overflow)
            {
                // Add Glyphs for overflow...
                RemoveBodyGlyphsForOverflow();
                AddBodyGlyphsForOverflow();
            }

            if (_toolStripAdornerWindowService is not null && _boundsToInvalidate != Rectangle.Empty)
            {
                _toolStripAdornerWindowService.Invalidate(_boundsToInvalidate);
                BehaviorService.Invalidate(_boundsToInvalidate);
            }

            if (KeyboardHandlingService.CutOrDeleteInProgress)
            {
                IComponent targetSelection = (itemIndex == -1) ? ToolStrip : ToolStrip.Items[itemIndex];
                // if the TemplateNode becomes the targetSelection, then set the targetSelection to null.
                if (targetSelection is not null)
                {
                    if (targetSelection is DesignerToolStripControlHost)
                    {
                        KeyboardHandlingService?.SelectedDesignerControl = targetSelection;

                        SelectionService.SetSelectedComponents(null, SelectionTypes.Replace);
                    }
                    else
                    {
                        SelectionService.SetSelectedComponents(new IComponent[] { targetSelection }, SelectionTypes.Replace);
                    }
                }
            }
        }
    }

    /// <summary>
    ///  Before a ToolStripItem is removed, open a transaction to batch the operation.
    /// </summary>
    private void ComponentChangeSvc_ComponentRemoving(object sender, ComponentEventArgs e)
    {
        if (e.Component is ToolStripItem item && item.Owner == Component)
        {
            Debug.Assert(_host is not null, "Why didn't we get a designer host?");
            Debug.Assert(_pendingTransaction is null, "Removing item with pending transaction?");
            try
            {
                _pendingTransaction = _host.CreateTransaction(SR.ToolStripDesignerTransactionRemovingItem);
                RaiseComponentChanging(TypeDescriptor.GetProperties(Component)[nameof(Items)]);
                if (e.Component is ToolStripDropDownItem dropDownItem)
                {
                    dropDownItem.HideDropDown();
                    _boundsToInvalidate = dropDownItem.DropDown.Bounds;
                }
            }
            catch
            {
                if (_pendingTransaction is not null)
                {
                    _pendingTransaction.Cancel();
                    _pendingTransaction = null;
                }
            }
        }
    }

    /// <summary>
    ///  Clean up the mess we've made!
    /// </summary>
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _disposed = true;
            if (_items is not null)
            {
                _items = null;
            }

            if (_undoEngine is not null)
            {
                _undoEngine.Undoing -= OnUndoing;
                _undoEngine.Undone -= OnUndone;
            }

            if (_componentChangeService is not null)
            {
                _componentChangeService.ComponentAdding -= ComponentChangeSvc_ComponentAdding;
                _componentChangeService.ComponentAdded -= ComponentChangeSvc_ComponentAdded;
                _componentChangeService.ComponentRemoving -= ComponentChangeSvc_ComponentRemoving;
                _componentChangeService.ComponentRemoved -= ComponentChangeSvc_ComponentRemoved;
                _componentChangeService.ComponentChanged -= ComponentChangeSvc_ComponentChanged;
            }

            if (_selectionService is not null)
            {
                _selectionService.SelectionChanged -= SelSvc_SelectionChanged;
                _selectionService.SelectionChanging -= SelSvc_SelectionChanging;
                _selectionService = null;
            }

            if (HasComponent)
            {
                EnableDragDrop(false);
            }

            // Dispose of the EditManager
            if (_editManager is not null)
            {
                ToolStripEditorManager.CloseManager();
                _editManager = null;
            }

            // Tear down the TemplateNode
            if (_tn is not null)
            {
                _tn.RollBack();
                _tn.CloseEditor();
                _tn = null;
            }

            // teardown the add item button.
            if (_miniToolStrip is not null)
            {
                _miniToolStrip.Dispose();
                _miniToolStrip = null;
            }

            // tearDown the EditorNode..
            if (_editorNode is not null)
            {
                _editorNode.Dispose();
                _editorNode = null;
            }

            if (ToolStrip is not null)
            {
                ToolStrip.OverflowButton.DropDown.Closing -= OnOverflowDropDownClosing;
                ToolStrip.OverflowButton.DropDownOpening -= OnOverFlowDropDownOpening;
                ToolStrip.OverflowButton.DropDownOpened -= OnOverFlowDropDownOpened;
                ToolStrip.OverflowButton.DropDownClosed -= OnOverFlowDropDownClosed;
                ToolStrip.OverflowButton.DropDown.Resize -= OnOverflowDropDownResize;
                ToolStrip.OverflowButton.DropDown.Paint -= OnOverFlowDropDownPaint;

                ToolStrip.Move -= OnToolStripMove;
                ToolStrip.VisibleChanged -= OnToolStripVisibleChanged;

                ToolStrip.ItemAdded -= OnItemAdded;

                ToolStrip.Resize -= ToolStrip_Resize;
                ToolStrip.DockChanged -= ToolStrip_Resize;
                ToolStrip.LayoutCompleted -= ToolStrip_LayoutCompleted;
            }

            // Tear off the ContextMenu.
            if (_toolStripContextMenu is not null)
            {
                _toolStripContextMenu.Dispose();
                _toolStripContextMenu = null;
            }

            // Always Remove all the glyphs we added
            if (HasComponent)
            {
                RemoveBodyGlyphsForOverflow();
                // tear off the OverFlow if its being shown
                if (ToolStrip.OverflowButton.DropDown.Visible)
                {
                    ToolStrip.OverflowButton.HideDropDown();
                }
            }

            if (_toolStripAdornerWindowService is not null)
            {
                _toolStripAdornerWindowService = null;
            }
        }

        base.Dispose(disposing);
    }

    /// <summary>
    ///  Creates a method signature in the source code file for the default event on the component and navigates
    ///  the user's cursor to that location in preparation to assign the default action.
    /// </summary>
    public override void DoDefaultAction()
    {
        // Don't Fire the Events if the Component is Inherited.
        if (InheritanceAttribute != InheritanceAttribute.InheritedReadOnly)
        {
            IComponent selectedItem = SelectionService.PrimarySelection as IComponent;
            if (selectedItem is null)
            {
                if (KeyboardHandlingService is not null)
                {
                    selectedItem = (IComponent)KeyboardHandlingService.SelectedDesignerControl;
                }
            }

            // if one of the sub-items is selected, delegate to it.
            if (selectedItem is ToolStripItem)
            {
                if (_host is not null)
                {
                    IDesigner itemDesigner = _host.GetDesigner(selectedItem);
                    if (itemDesigner is not null)
                    {
                        itemDesigner.DoDefaultAction();
                        return;
                    }
                }
            }

            base.DoDefaultAction();
        }
    }

    /// <summary>
    ///  We add our BodyGlyphs as well as bodyGlyphs for the ToolStripItems here.
    /// </summary>
    protected override ControlBodyGlyph GetControlGlyph(GlyphSelectionType selectionType)
    {
        // Get the glyphs iff Handle is created for the toolStrip.
        if (!ToolStrip.IsHandleCreated)
        {
            return null;
        }

        if (TryGetService(out SelectionManager selectionManager) && ToolStrip is not null && CanAddItems && ToolStrip.Visible)
        {
            object primarySelection = SelectionService.PrimarySelection;
            Behavior.Behavior toolStripBehavior = new ToolStripItemBehavior();

            // Sometimes the Collection changes when the ToolStrip gets the Selection and we are in a dummy InSitu
            // edit so remove that before accessing the collection
            if (ToolStrip.Items.Count > 0)
            {
                ToolStripItem[] items = new ToolStripItem[ToolStrip.Items.Count];
                ToolStrip.Items.CopyTo(items, 0);
                foreach (ToolStripItem toolItem in items)
                {
                    if (toolItem is not null)
                    {
                        ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)_host.GetDesigner(toolItem);
                        bool isPrimary = (toolItem == primarySelection);
                        if (!isPrimary &&
                            itemDesigner is not null &&
                            itemDesigner.IsEditorActive)
                        {
                            itemDesigner.Editor.Commit(false, false);
                        }
                    }
                }
            }

            // now walk the ToolStrip and add glyphs for each of it's children
            foreach (ToolStripItem item in ToolStrip.Items)
            {
                if (item is DesignerToolStripControlHost)
                {
                    continue;
                }

                // make sure it's on the ToolStrip...
                if (item.Placement == ToolStripItemPlacement.Main)
                {
                    ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)_host.GetDesigner(item);
                    if (itemDesigner is not null)
                    {
                        bool isPrimary = (item == primarySelection);
                        if (isPrimary)
                        {
                            ((ToolStripItemBehavior)toolStripBehavior)._dragBoxFromMouseDown = _dragBoxFromMouseDown;
                        }

                        // Get Back the Current Bounds if current selection is not a primary selection
                        if (!isPrimary)
                        {
                            item.AutoSize = itemDesigner is null || itemDesigner.AutoSize;
                        }

                        Rectangle itemBounds = itemDesigner.GetGlyphBounds();
                        Control parent = ToolStrip.Parent;
                        Rectangle parentBounds = BehaviorService.ControlRectInAdornerWindow(parent);
                        if (IsGlyphTotallyVisible(itemBounds, parentBounds) && item.Visible)
                        {
                            // Add Glyph ONLY AFTER item width is changed...
                            ToolStripItemGlyph bodyGlyphForItem = new(item, itemDesigner, itemBounds, toolStripBehavior);
                            itemDesigner._bodyGlyph = bodyGlyphForItem;
                            // Add ItemGlyph to the Collection
                            selectionManager.BodyGlyphAdorner.Glyphs.Add(bodyGlyphForItem);
                        }
                    }
                }
            }
        }

        return (base.GetControlGlyph(selectionType));
    }

    /// <summary>
    ///  We add our SelectionGlyphs here. Since ToolStripItems are components we add the SelectionGlyphs
    ///  for those in this call as well.
    /// </summary>
    public override GlyphCollection GetGlyphs(GlyphSelectionType selType)
    {
        // get the default glyphs for this component.
        GlyphCollection glyphs = [];
        ICollection selComponents = SelectionService.GetSelectedComponents();
        foreach (object comp in selComponents)
        {
            if (comp is ToolStrip)
            {
                GlyphCollection toolStripGlyphs = base.GetGlyphs(selType);
                glyphs.AddRange(toolStripGlyphs);
            }
            else
            {
                if (comp is ToolStripItem item && item.Visible)
                {
                    ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)_host.GetDesigner(item);
                    itemDesigner?.GetGlyphs(ref glyphs, StandardBehavior);
                }
            }
        }

        if ((SelectionRules & SelectionRules.Moveable) != 0 && InheritanceAttribute != InheritanceAttribute.InheritedReadOnly && (selType != GlyphSelectionType.NotSelected))
        {
            // Get the adorner window-relative coordinates for the container control
            Point loc = BehaviorService.ControlToAdornerWindow((Control)Component);
            Rectangle translatedBounds = new(loc, ((Control)Component).Size);
            int glyphOffset = (int)(DesignerUtils.s_containerGrabHandleSize * .5);
            // if the control is too small for our ideal position...
            if (translatedBounds.Width < 2 * DesignerUtils.s_containerGrabHandleSize)
            {
                glyphOffset = -1 * glyphOffset;
            }

            ContainerSelectorBehavior behavior = new(ToolStrip, Component.Site, true);
            ContainerSelectorGlyph containerSelectorGlyph = new(translatedBounds, DesignerUtils.s_containerGrabHandleSize, glyphOffset, behavior);
            glyphs.Insert(0, containerSelectorGlyph);
        }

        return glyphs;
    }

    /// <summary>
    ///  Allow hit testing over the AddNewItem button only.
    /// </summary>
    protected override bool GetHitTest(Point point)
    {
        // Convert to client coordinates.
        point = Control.PointToClient(point);

        if (_miniToolStrip is not null && _miniToolStrip.Visible && AddItemRect.Contains(point))
        {
            return true;
        }

        if (OverFlowButtonRect.Contains(point))
        {
            return true;
        }

        return base.GetHitTest(point);
    }

    /// <summary>
    ///  Get the designer set up to run.
    /// </summary>
    // EditorServiceContext updated to add Edit Items verb.
    public override void Initialize(IComponent component)
    {
        base.Initialize(component);
        AutoResizeHandles = true;
        _host = GetRequiredService<IDesignerHost>();
        _componentChangeService = _host.GetService<IComponentChangeService>();

        _undoEngine ??= GetService<UndoEngine>();
        if (_undoEngine is not null)
        {
            _undoEngine.Undoing += OnUndoing;
            _undoEngine.Undone += OnUndone;
        }

        // initialize new Manager For Editing ToolStrips
        _editManager = new ToolStripEditorManager(component);

        // Setup the dropdown if our handle has been created.
        if (Control.IsHandleCreated)
        {
            InitializeNewItemDropDown();
        }
        else
        {
            Control.HandleCreated += Control_HandleCreated;
        }

        // Attach notifications.
        if (_componentChangeService is not null)
        {
            _componentChangeService.ComponentAdding += ComponentChangeSvc_ComponentAdding;
            _componentChangeService.ComponentAdded += ComponentChangeSvc_ComponentAdded;
            _componentChangeService.ComponentRemoving += ComponentChangeSvc_ComponentRemoving;
            _componentChangeService.ComponentRemoved += ComponentChangeSvc_ComponentRemoved;
            _componentChangeService.ComponentChanged += ComponentChangeSvc_ComponentChanged;
        }

        // Hookup to the AdornerService for the overflow dropdown to be parent properly.
        _toolStripAdornerWindowService = GetService<ToolStripAdornerWindowService>();

        SelectionService.SelectionChanging += SelSvc_SelectionChanging;
        SelectionService.SelectionChanged += SelSvc_SelectionChanged;

        // Sink size changes.
        ToolStrip.Resize += ToolStrip_Resize;
        ToolStrip.DockChanged += ToolStrip_Resize;
        ToolStrip.LayoutCompleted += ToolStrip_LayoutCompleted;

        // Make sure the overflow is not topLevel
        ToolStrip.OverflowButton.DropDown.TopLevel = false;

        // Init the verb.
        if (CanAddItems)
        {
            new EditorServiceContext(this, TypeDescriptor.GetProperties(Component)[nameof(Items)], SR.ToolStripItemCollectionEditorVerb);

            // Add the EditService so that the ToolStrip can do its own Tab and Keyboard Handling
            if (GetService<ToolStripKeyboardHandlingService>() is null)
            {
                new ToolStripKeyboardHandlingService(Component.Site);
            }

            // Add the InSituEditService so that the ToolStrip can do its own Tab and Keyboard Handling
            if (GetService<ISupportInSituService>() is null)
            {
                new ToolStripInSituService(Component.Site);
            }
        }

        // ToolStrip is selected...
        _toolStripSelected = true;
        // Reset the TemplateNode Selection if any...
        if (_keyboardHandlingService is not null)
        {
            KeyboardHandlingService.SelectedDesignerControl = null;
        }
    }

    /// <summary>
    ///  ControlDesigner overrides this method. It will look at the default property for the control and,
    ///  if it is of type string, it will set this property's value to the name of the component.
    ///  It only does this if the designer has been configured with this option in the options service.
    ///  This method also connects the control to its parent and positions it. If you override this method,
    ///  you should always call base.
    /// </summary>
    public override void InitializeNewComponent(IDictionary defaultValues)
    {
        Control parent = defaultValues is not null ? defaultValues["Parent"] as Control : null;
        Form parentForm = _host.RootComponent as Form;
        MenuStrip parentMenu = null;
        FormDocumentDesigner parentFormDesigner = null;
        if (parentForm is not null)
        {
            parentFormDesigner = _host.GetDesigner(parentForm) as FormDocumentDesigner;

            parentMenu = parentForm.Controls.OfType<MenuStrip>().FirstOrDefault();
            if (parentMenu is not null)
            {
                // Stash off the menu strip while we initialize
                parentForm.Controls.Remove(parentMenu);
            }
        }

        ToolStripPanel parentPanel = parent as ToolStripPanel;
        // smoke the Dock Property if the toolStrip is getting parented to the ContentPanel.
        if (parentPanel is null && parent is ToolStripContentPanel)
        {
            // smoke the dock property whenever we add a toolstrip to a toolstrip panel.
            PropertyDescriptor dockProp = TypeDescriptor.GetProperties(ToolStrip)["Dock"];
            dockProp?.SetValue(ToolStrip, DockStyle.None);
        }

        // Set up parenting and all the base functionality.
        if (parentPanel is null || ToolStrip is MenuStrip)
        {
            base.InitializeNewComponent(defaultValues);
        }

        if (parentFormDesigner is not null)
        {
            // Add MenuStrip back.
            if (parentMenu is MenuStrip menuStrip)
            {
                parentForm.Controls.Add(menuStrip);
            }

            // Set MainMenuStrip property
            if (ToolStrip is MenuStrip)
            {
                PropertyDescriptor mainMenuStripProperty = TypeDescriptor.GetProperties(parentForm)["MainMenuStrip"];
                if (mainMenuStripProperty is not null && mainMenuStripProperty.GetValue(parentForm) is null)
                {
                    mainMenuStripProperty.SetValue(parentForm, ToolStrip as MenuStrip);
                }
            }
        }

        if (parentPanel is not null)
        {
            if (ToolStrip is not MenuStrip)
            {
                PropertyDescriptor controlsProp = TypeDescriptor.GetProperties(parentPanel)["Controls"];

                _componentChangeService?.OnComponentChanging(parentPanel, controlsProp);

                parentPanel.Join(ToolStrip, parentPanel.Rows.Length);

                _componentChangeService?.OnComponentChanged(parentPanel, controlsProp, parentPanel.Controls, parentPanel.Controls);

                // Try to fire ComponentChange on the Location Property for ToolStrip.
                PropertyDescriptor locationProp = TypeDescriptor.GetProperties(ToolStrip)["Location"];
                _componentChangeService?.OnComponentChanging(ToolStrip, locationProp);
                _componentChangeService?.OnComponentChanged(ToolStrip, locationProp);
            }
        }

        // If we are added to any container other than ToolStripPanel.
        else if (parent is not null)
        {
            // If we are adding the MenuStrip
            // put it at the Last in the Controls Collection so it gets laid out first.
            if (ToolStrip is MenuStrip)
            {
                int index = -1;
                foreach (Control c in parent.Controls)
                {
                    if (c is ToolStrip && (c != ToolStrip))
                    {
                        index = parent.Controls.IndexOf(c);
                    }
                }

                if (index == -1)
                {
                    // always place the toolStrip first.
                    index = parent.Controls.Count - 1;
                }

                parent.Controls.SetChildIndex(ToolStrip, index);
            }

            // If we are not a MenuStrip then we still need to be first to be laid out "after the menuStrip"
            else
            {
                int index = -1;
                foreach (Control c in parent.Controls)
                {
                    // If we found an existing toolstrip (and not a menuStrip) then we can just return ..
                    // the base would have done correct parenting for us.
                    MenuStrip menu = c as MenuStrip;
                    if (c is ToolStrip && menu is null)
                    {
                        return;
                    }

                    if (menu is not null)
                    {
                        index = parent.Controls.IndexOf(c);
                        break;
                    }
                }

                if (index == -1)
                {
                    // always place the toolStrip first.
                    index = parent.Controls.Count;
                }

                parent.Controls.SetChildIndex(ToolStrip, index - 1);
            }
        }
    }

    /// <summary>
    ///  Setup the "AddNewItem" button
    /// </summary>
    private void InitializeNewItemDropDown()
    {
        if (!CanAddItems || !SupportEditing)
        {
            return;
        }

        AddNewTemplateNode();

        // Set up the right visibility state for the ToolStrip.
        SelSvc_SelectionChanged(null, EventArgs.Empty);
    }

    /// <summary>
    ///  This is called to ascertain if the Glyph is totally visible. This is called from ToolStripMenuItemDesigner too.
    /// </summary>
    internal static bool IsGlyphTotallyVisible(Rectangle itemBounds, Rectangle parentBounds)
    {
        return parentBounds.Contains(itemBounds);
    }

    /// <summary>
    ///  Returns true if the item is on the overflow.
    /// </summary>
    private static bool ItemParentIsOverflow(ToolStripItem item)
    {
        ToolStripDropDown topmost = item.Owner as ToolStripDropDown;
        if (topmost is not null)
        {
            // walk back up the chain of windows to get the topmost
            while (topmost is not null and not ToolStripOverflow)
            {
                topmost = topmost?.OwnerItem.GetCurrentParent() as ToolStripDropDown;
            }
        }

        return (topmost is ToolStripOverflow);
    }

    /// <summary>
    ///  Sets up the add new button, and invalidates the behavior glyphs if needed so they always stay in sync.
    /// </summary>
    private void LayoutToolStrip()
    {
        if (!_disposed)
        {
            ToolStrip.PerformLayout();
        }
    }

    internal static string NameFromText(string text, Type componentType, IServiceProvider serviceProvider, bool adjustCapitalization)
    {
        string name = NameFromText(text, componentType, serviceProvider);
        if (adjustCapitalization)
        {
            string nameOfRandomItem = NameFromText(null, typeof(ToolStripMenuItem),
                serviceProvider);
            if (!string.IsNullOrEmpty(nameOfRandomItem) && char.IsUpper(nameOfRandomItem[0]))
            {
                name = char.ToUpper(name[0], CultureInfo.InvariantCulture) + name[1..];
            }
        }

        return name;
    }

    /// <summary>
    ///  Computes a name from a text label by removing all spaces and non-alphanumeric characters.
    /// </summary>
    internal static string NameFromText(string text, Type componentType, IServiceProvider serviceProvider)
    {
        if (serviceProvider is null)
        {
            return null;
        }

        INameCreationService nameCreate = serviceProvider.GetService(typeof(INameCreationService)) as INameCreationService;
        IContainer container = (IContainer)serviceProvider.GetService(typeof(IContainer));
        string defaultName;
        if (nameCreate is not null && container is not null)
        {
            defaultName = nameCreate.CreateName(container, componentType);
        }
        else
        {
            return null;
        }

        Debug.Assert(defaultName is not null && defaultName.Length > 0, "Couldn't create default name for item");

        if (text is null || text.Length == 0 || text == "-")
        {
            return defaultName;
        }

        string nameSuffix = componentType.Name;
        // remove all the non letter and number characters. Append length of the item name...
        Text.StringBuilder name = new(text.Length + nameSuffix.Length);
        bool nextCharToUpper = false;
        for (int i = 0; i < text.Length; i++)
        {
            char c = text[i];
            if (nextCharToUpper)
            {
                if (char.IsLower(c))
                {
                    c = char.ToUpper(c, CultureInfo.CurrentCulture);
                }

                nextCharToUpper = false;
            }

            if (char.IsLetterOrDigit(c))
            {
                if (name.Length == 0)
                {
                    if (char.IsDigit(c))
                    {
                        // most languages don't allow a digit as the first char in an identifier.
                        continue;
                    }

                    if (char.IsLower(c) != char.IsLower(defaultName[0]))
                    {
                        // match up the first char of the generated identifier with the case of the default.
                        c = char.IsLower(c)
                            ? char.ToUpper(c, CultureInfo.CurrentCulture)
                            : char.ToLower(c, CultureInfo.CurrentCulture);
                    }
                }

                name.Append(c);
            }
            else
            {
                if (char.IsWhiteSpace(c))
                {
                    nextCharToUpper = true;
                }
            }
        }

        if (name.Length == 0)
        {
            return defaultName;
        }

        name.Append(nameSuffix);
        string baseName = name.ToString();

        // verify we have a valid name. If not, start appending numbers if it matches one in the container.
        // see if this name matches another one in the container..
        object existingComponent = container.Components[baseName];

        if (existingComponent is null)
        {
            if (!nameCreate.IsValidName(baseName))
            {
                // we don't have a name collision but this still isn't a valid name...
                // something is wrong and we can't make a valid identifier out of this so bail.
                return defaultName;
            }
            else
            {
                return baseName;
            }
        }
        else
        {
            // start appending numbers.
            string newName = baseName;
            for (int indexer = 1; !nameCreate.IsValidName(newName) || container.Components[newName] is not null; indexer++)
            {
                newName = $"{baseName}{indexer}";
            }

            return newName;
        }
    }

    /// <summary>
    ///  DesignerContextMenu should be shown when the ToolStripDesigner.
    /// </summary>
    protected override void OnContextMenu(int x, int y)
    {
        Component selComp = SelectionService.PrimarySelection as Component;
        if (selComp is ToolStrip)
        {
            DesignerContextMenu.Show(x, y);
        }
    }

    protected override void OnDragEnter(DragEventArgs de)
    {
        base.OnDragEnter(de);
        SetDragDropEffects(de);
    }

    protected override void OnDragOver(DragEventArgs de)
    {
        base.OnDragOver(de);
        SetDragDropEffects(de);
    }

    /// <summary>
    ///  Add item on Drop and it its a MenuItem, open its dropDown.
    /// </summary>
    protected override void OnDragDrop(DragEventArgs de)
    {
        base.OnDragDrop(de);
        // There is a "drop region" before firstItem which is not included in the "ToolStrip Item glyphs"
        // so if the drop point falls in this drop region we should insert the items at the head instead
        // of the tail of the toolStrip.
        bool dropAtHead = false;
        ToolStrip parentToolStrip = ToolStrip;
        Point offset = new(de.X, de.Y);
        offset = parentToolStrip.PointToClient(offset);
        if (ToolStrip.Orientation == Orientation.Horizontal)
        {
            if (ToolStrip.RightToLeft == RightToLeft.Yes)
            {
                if (offset.X >= parentToolStrip.Items[0].Bounds.X)
                {
                    dropAtHead = true;
                }
            }
            else if (offset.X <= parentToolStrip.Items[0].Bounds.X)
            {
                dropAtHead = true;
            }
        }
        else
        {
            if (offset.Y <= parentToolStrip.Items[0].Bounds.Y)
            {
                dropAtHead = true;
            }
        }

        if (!(de.Data is ToolStripItemDataObject data) || data.Owner != parentToolStrip)
        {
            return;
        }

        string transDesc;
        List<ToolStripItem> dragComponents = data.DragComponents;
        ToolStripItem primaryItem = data.PrimarySelection;
        int primaryIndex = -1;
        bool copy = (de.Effect == DragDropEffects.Copy);

        if (dragComponents.Count == 1)
        {
            string name = TypeDescriptor.GetComponentName(dragComponents[0]);
            if (name is null || name.Length == 0)
            {
                name = dragComponents[0].GetType().Name;
            }

            transDesc = string.Format(copy ? SR.BehaviorServiceCopyControl : SR.BehaviorServiceMoveControl, name);
        }
        else
        {
            transDesc = string.Format(copy ? SR.BehaviorServiceCopyControls : SR.BehaviorServiceMoveControls, dragComponents.Count);
        }

        // create a transaction so this happens as an atomic unit.
        DesignerTransaction changeParent = _host.CreateTransaction(transDesc);
        try
        {
            if (TryGetService(out IComponentChangeService changeService))
            {
                changeService.OnComponentChanging(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)[nameof(Items)]);
            }

            IReadOnlyList<IComponent> components;

            // If we are copying, then we want to make a copy of the components we are dragging
            if (copy)
            {
                // Remember the primary selection if we had one
                if (primaryItem is not null)
                {
                    primaryIndex = dragComponents.IndexOf(primaryItem);
                }

                KeyboardHandlingService?.CopyInProgress = true;

                components = DesignerUtils.CopyDragObjects(dragComponents, Component.Site);
                KeyboardHandlingService?.CopyInProgress = false;

                if (primaryIndex != -1)
                {
                    primaryItem = components[primaryIndex] as ToolStripItem;
                }
            }
            else
            {
                components = dragComponents;
            }

            if (de.Effect == DragDropEffects.Move || copy)
            {
                // Add the item.
                for (int i = 0; i < components.Count; i++)
                {
                    if (dropAtHead)
                    {
                        parentToolStrip.Items.Insert(0, components[i] as ToolStripItem);
                    }
                    else
                    {
                        parentToolStrip.Items.Add(components[i] as ToolStripItem);
                    }
                }

                // show the dropDown for the primarySelection before the Drag-Drop operation started.
                if (primaryItem is ToolStripDropDownItem primaryDropDownItem)
                {
                    if (_host.GetDesigner(primaryDropDownItem) is ToolStripMenuItemDesigner dropDownItemDesigner)
                    {
                        dropDownItemDesigner.InitializeDropDown();
                    }
                }

                // Set the Selection ..
                SelectionService.SetSelectedComponents(new IComponent[] { primaryItem }, SelectionTypes.Primary | SelectionTypes.Replace);
            }

            changeService?.OnComponentChanged(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)[nameof(Items)]);

            // Fire extra changing/changed events so that the order is "restored" after undo/redo
            if (copy)
            {
                if (changeService is not null)
                {
                    changeService.OnComponentChanging(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)[nameof(Items)]);
                    changeService.OnComponentChanged(parentToolStrip, TypeDescriptor.GetProperties(parentToolStrip)[nameof(Items)]);
                }
            }

            // Refresh Glyphs...
            BehaviorService.SyncSelection();
        }

        catch
        {
            if (changeParent is not null)
            {
                changeParent.Cancel();
                changeParent = null;
            }
        }
        finally
        {
            changeParent?.Commit();
        }
    }

    /// <summary>
    ///  Every time we add Item .. the TemplateNode needs to go at the end if its not there.
    /// </summary>
    private void OnItemAdded(object sender, ToolStripItemEventArgs e)
    {
        if (_editorNode is not null && (e.Item != _editorNode))
        {
            int currentIndexOfEditor = ToolStrip.Items.IndexOf(_editorNode);
            if (currentIndexOfEditor == -1 || currentIndexOfEditor != ToolStrip.Items.Count - 1)
            {
                // if the editor is not there or not at the end, add it to the end.
                ToolStrip.ItemAdded -= OnItemAdded;
                ToolStrip.SuspendLayout();
                ToolStrip.Items.Add(_editorNode);
                ToolStrip.ResumeLayout();
                ToolStrip.ItemAdded += OnItemAdded;
            }
        }

        LayoutToolStrip();
    }

    /// <summary>
    ///  Overridden so that the ToolStrip honors dragging only through container selector glyph.
    /// </summary>
    protected override void OnMouseDragMove(int x, int y)
    {
        if (!SelectionService.GetComponentSelected(ToolStrip))
        {
            base.OnMouseDragMove(x, y);
        }
    }

    /// <summary>
    ///  Controls the dismissal of the drop down, here - we just cancel it
    /// </summary>
    private void OnOverflowDropDownClosing(object sender, ToolStripDropDownClosingEventArgs e)
    {
        // always dismiss this so we don't collapse the dropdown when the user clicks @ design time
        e.Cancel = (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked);
    }

    /// <summary>
    ///  Remove the Glyphs for Items on the overflow when the Overflow closes.
    /// </summary>
    private void OnOverFlowDropDownClosed(object sender, EventArgs e)
    {
        if (_toolStripAdornerWindowService is not null && sender is ToolStripDropDownItem ddi)
        {
            _toolStripAdornerWindowService.Invalidate(ddi.DropDown.Bounds);
            RemoveBodyGlyphsForOverflow();
        }

        // select the last item on the parent toolStrip if the current selection is on the DropDown.
        if (SelectionService.PrimarySelection is ToolStripItem curSel && curSel.IsOnOverflow)
        {
            ToolStripItem nextItem = ToolStrip.GetNextItem(ToolStrip.OverflowButton, ArrowDirection.Left);
            if (nextItem is not null)
            {
                SelectionService.SetSelectedComponents(new IComponent[] { nextItem }, SelectionTypes.Replace);
            }
        }
    }

    /// <summary>
    ///  Add Glyphs when the OverFlow opens ....
    /// </summary>
    private void OnOverFlowDropDownOpened(object sender, EventArgs e)
    {
        // Show the TemplateNode
        if (_editorNode is not null)
        {
            _editorNode.Control.Visible = true;
            _editorNode.Visible = true;
        }

        ToolStripDropDownItem ddi = sender as ToolStripDropDownItem;
        if (ddi is not null)
        {
            RemoveBodyGlyphsForOverflow();
            AddBodyGlyphsForOverflow();
        }

        // select the last item on the parent toolStrip if the current selection is on the DropDown.
        if (!(SelectionService.PrimarySelection is ToolStripItem curSel) || (curSel is not null && !curSel.IsOnOverflow))
        {
            ToolStripItem nextItem = ddi.DropDown.GetNextItem(null, ArrowDirection.Down);
            if (nextItem is not null)
            {
                SelectionService.SetSelectedComponents(new IComponent[] { nextItem }, SelectionTypes.Replace);
                BehaviorService.Invalidate(BehaviorService.ControlRectInAdornerWindow(ToolStrip));
            }
        }
    }

    /// <summary>
    ///  In Order to Draw the Selection Glyphs we need to force repainting on the AdornerWindow.
    ///  This method forces the repaint.
    /// </summary>
    private void OnOverFlowDropDownPaint(object sender, PaintEventArgs e)
    {
        foreach (ToolStripItem item in ToolStrip.Items)
        {
            if (item.Visible
                && item.IsOnOverflow
                && SelectionService.GetComponentSelected(item)
                && _host.GetDesigner(item) is ToolStripItemDesigner designer)
            {
                Rectangle r = designer.GetGlyphBounds();
                ToolStripDesignerUtils.GetAdjustedBounds(item, ref r);
                r.Inflate(GLYPHBORDER, GLYPHBORDER);

                // This will allow any Glyphs to re-paint after this control and its designer has painted
                GetService<BehaviorService>()?.ProcessPaintMessage(r);
            }
        }
    }

    /// <summary>
    ///  Change the parent of the overFlow so that it is parented to the ToolStripAdornerWindow
    /// </summary>
    private void OnOverFlowDropDownOpening(object sender, EventArgs e)
    {
        ToolStripDropDownItem ddi = sender as ToolStripDropDownItem;
        if (ddi.DropDown.TopLevel)
        {
            ddi.DropDown.TopLevel = false;
        }

        if (_toolStripAdornerWindowService is not null)
        {
            ToolStrip.SuspendLayout();
            ddi.DropDown.Parent = _toolStripAdornerWindowService.ToolStripAdornerWindowControl;
            ToolStrip.ResumeLayout();
        }
    }

    /// <summary>
    ///  When Items change the size, Recalculate the glyph sizes.
    /// </summary>
    private void OnOverflowDropDownResize(object sender, EventArgs e)
    {
        ToolStripDropDown dropDown = sender as ToolStripDropDown;
        if (dropDown.Visible)
        {
            // Re-Add the Glyphs to refresh the bounds... and Add new ones if new items get pushed into the OverFlow.
            RemoveBodyGlyphsForOverflow();
            AddBodyGlyphsForOverflow();
        }

        if (_toolStripAdornerWindowService is not null && dropDown is not null)
        {
            _toolStripAdornerWindowService.Invalidate();
        }
    }

    /// <summary>
    ///  Set proper cursor
    /// </summary>
    protected override void OnSetCursor()
    {
        _toolboxService ??= GetService<IToolboxService>();

        if (_toolboxService is null
            || !_toolboxService.SetCursor()
            || InheritanceAttribute.Equals(InheritanceAttribute.InheritedReadOnly))
        {
            Cursor.Current = Cursors.Default;
        }
    }

    /// <summary>
    ///  ResumeLayout after Undone.
    /// </summary>
    private void OnUndone(object source, EventArgs e)
    {
        if (_editorNode is not null && (ToolStrip.Items.IndexOf(_editorNode) == -1))
        {
            ToolStrip.Items.Add(_editorNode);
        }

        if (_undoingCalled)
        {
            // StatusStrip required a ResumeLayout and then a performLayout... So that the Layout is proper after any user-transaction UNDONE.
            ToolStrip.ResumeLayout(true/*performLayout*/);
            ToolStrip.PerformLayout();
            // ReInitialize the Glyphs after Layout is resumed !!
            if (SelectionService.PrimarySelection is ToolStripDropDownItem selectedItem)
            {
                if (_host.GetDesigner(selectedItem) is ToolStripMenuItemDesigner selectedItemDesigner)
                {
                    selectedItemDesigner.InitializeBodyGlyphsForItems(false, selectedItem);
                    selectedItemDesigner.InitializeBodyGlyphsForItems(true, selectedItem);
                }
            }

            _undoingCalled = false;
        }

        BehaviorService.SyncSelection();
    }

    /// <summary>
    ///  SuspendLayout before unDoing.
    /// </summary>
    private void OnUndoing(object source, EventArgs e)
    {
        if (CheckIfItemSelected() || SelectionService.GetComponentSelected(ToolStrip))
        {
            _undoingCalled = true;
            ToolStrip.SuspendLayout();
        }
    }

    /// <summary>
    ///  SyncSelection on ToolStrip move.
    /// </summary>
    private void OnToolStripMove(object sender, EventArgs e)
    {
        if (SelectionService.GetComponentSelected(ToolStrip))
        {
            BehaviorService.SyncSelection();
        }
    }

    /// <summary>
    ///  Remove all the glyphs we were are not visible..
    /// </summary>
    private void OnToolStripVisibleChanged(object sender, EventArgs e)
    {
        if (sender is ToolStrip tool && !tool.Visible)
        {
            SelectionManager selectionManager = GetService<SelectionManager>();
            Glyph[] currentBodyGlyphs = new Glyph[selectionManager.BodyGlyphAdorner.Glyphs.Count];
            selectionManager.BodyGlyphAdorner.Glyphs.CopyTo(currentBodyGlyphs, 0);

            // Remove the ToolStripItemGlyphs.
            foreach (Glyph g in currentBodyGlyphs)
            {
                if (g is ToolStripItemGlyph)
                {
                    selectionManager.BodyGlyphAdorner.Glyphs.Remove(g);
                }
            }
        }
    }

    /// <summary>
    ///  Allows a designer to filter the set of properties the component it is designing will expose through
    ///  the TypeDescriptor object. This method is called immediately before its corresponding "Post" method.
    ///  If you are overriding this method you should call the base implementation before
    ///  you perform your own filtering.
    /// </summary>
    protected override void PreFilterProperties(IDictionary properties)
    {
        base.PreFilterProperties(properties);
        PropertyDescriptor prop;
        string[] shadowProps =
        [
           "Visible",
           "AllowDrop",
           "AllowItemReorder"
        ];
        Attribute[] empty = [];
        for (int i = 0; i < shadowProps.Length; i++)
        {
            prop = (PropertyDescriptor)properties[shadowProps[i]];
            if (prop is not null)
            {
                properties[shadowProps[i]] = TypeDescriptor.CreateProperty(typeof(ToolStripDesigner), prop, empty);
            }
        }
    }

    /// <summary>
    ///  Remove the glyphs for individual items on the DropDown.
    /// </summary>
    private void RemoveBodyGlyphsForOverflow()
    {
        // now walk the ToolStrip and add glyphs for each of it's children
        foreach (ToolStripItem item in ToolStrip.Items)
        {
            if (item is DesignerToolStripControlHost)
            {
                continue;
            }

            // make sure it's on the Overflow...
            if (item.Placement == ToolStripItemPlacement.Overflow)
            {
                ToolStripItemDesigner dropDownItemDesigner = (ToolStripItemDesigner)_host.GetDesigner(item);
                if (dropDownItemDesigner is not null)
                {
                    ControlBodyGlyph glyph = dropDownItemDesigner._bodyGlyph;
                    if (glyph is not null && _toolStripAdornerWindowService is not null && _toolStripAdornerWindowService.DropDownAdorner.Glyphs.Contains(glyph))
                    {
                        _toolStripAdornerWindowService.DropDownAdorner.Glyphs.Remove(glyph);
                    }
                }
            }
        }
    }

    /// <summary>
    ///  Called from the ToolStripItemGlyph to roll back the TemplateNode Edition on the Parent ToolStrip.
    /// </summary>
    internal void RollBack()
    {
        if (_tn is not null)
        {
            _tn.RollBack();
            _editorNode.Width = _tn.EditorToolStrip.Width;
        }
    }

    /// <summary>
    ///  Resets the ToolStrip Visible to be the default value
    /// </summary>
    private void ResetVisible()
    {
        Visible = true;
    }

    /// <summary>
    ///  When the Drag Data does not contain ToolStripItem; change the dragEffect to None;
    ///  This will result current cursor to change into NO-SMOKING cursor.
    /// </summary>
    private void SetDragDropEffects(DragEventArgs de)
    {
        if (de.Data is ToolStripItemDataObject data)
        {
            de.Effect = data.Owner != ToolStrip
                ? DragDropEffects.None
                : (Control.ModifierKeys == Keys.Control) ? DragDropEffects.Copy : DragDropEffects.Move;
        }
    }

    /// <summary>
    ///  When selection changes to the ToolStrip, show the "AddItemsButton", when it leaves, hide it.
    /// </summary>
    private void SelSvc_SelectionChanging(object sender, EventArgs e)
    {
        if (_toolStripSelected)
        {
            // first commit the node
            if (_tn is not null && _tn.Active)
            {
                _tn.Commit(false, false);
            }
        }

        bool showToolStrip = CheckIfItemSelected();
        // Check All the SelectedComponents to find is toolstrips are selected
        if (!showToolStrip && !SelectionService.GetComponentSelected(ToolStrip))
        {
            ToolStrip.Visible = _currentVisible;
            if (!_currentVisible && _parentNotVisible)
            {
                ToolStrip.Parent.Visible = _currentVisible;
                _parentNotVisible = false;
            }

            if (ToolStrip.OverflowButton.DropDown.Visible)
            {
                ToolStrip.OverflowButton.HideDropDown();
            }

            // Always Hide the EditorNode if the ToolStrip Is Not Selected...
            _editorNode?.Visible = false;

            // Show Hide Items...
            ShowHideToolStripItems(false);
            _toolStripSelected = false;
        }
    }

    /// <summary>
    ///  When selection changes to the ToolStrip, show the "AddItemsButton", when it leaves, hide it.
    /// </summary>
    private void SelSvc_SelectionChanged(object sender, EventArgs e)
    {
        if (_miniToolStrip is not null && _host is not null)
        {
            bool itemSelected = CheckIfItemSelected();
            bool showToolStrip = itemSelected || SelectionService.GetComponentSelected(ToolStrip);
            // Check All the SelectedComponents to find is toolstrips are selected
            if (showToolStrip)
            {
                // If now the ToolStrip is selected,, Hide its Overflow

                if (SelectionService.GetComponentSelected(ToolStrip))
                {
                    if (!DontCloseOverflow && ToolStrip.OverflowButton.DropDown.Visible)
                    {
                        ToolStrip.OverflowButton.HideDropDown();
                    }
                }

                // Show Hide Items...
                ShowHideToolStripItems(true);
                if (!_currentVisible || !Control.Visible)
                {
                    // Since the control wasn't visible make it visible
                    Control.Visible = true;
                    // make the current parent visible too.
                    if (ToolStrip.Parent is ToolStripPanel && !ToolStrip.Parent.Visible)
                    {
                        _parentNotVisible = true;
                        ToolStrip.Parent.Visible = true;
                    }

                    // Since the GetBodyGlyphs is called before we come here in this case where the ToolStrip
                    // is going from visible==false to visible==true we need to re-add the glyphs for the items.
                    BehaviorService.SyncSelection();
                }

                // Always Show the EditorNode if the ToolStripIsSelected and is PrimarySelection or one of item is selected.
                if (_editorNode is not null && (SelectionService.PrimarySelection == ToolStrip || itemSelected))
                {
                    bool originalSyncSelection = FireSyncSelection;
                    try
                    {
                        FireSyncSelection = true;
                        _editorNode.Visible = true;
                    }
                    finally
                    {
                        FireSyncSelection = originalSyncSelection;
                    }
                }

                _toolStripSelected = true;
            }
        }
    }

    /// <summary>
    ///  Determines when should the Visible property be serialized.
    /// </summary>
    private bool ShouldSerializeVisible() => !Visible;

    /// <summary>
    ///  Determines when should the AllowDrop property be serialized.
    /// </summary>
    private bool ShouldSerializeAllowDrop() => (bool)ShadowProperties[nameof(AllowDrop)];

    /// <summary>
    ///  Determines when should the AllowItemReorder property be serialized.
    /// </summary>
    private bool ShouldSerializeAllowItemReorder() => (bool)ShadowProperties[nameof(AllowItemReorder)];

    /// <summary>
    ///  This is the method that gets called when the Designer has to show the InSitu Edit Node,
    /// </summary>
    internal void ShowEditNode(bool clicked)
    {
        // SPECIAL LOGIC TO MIMIC THE MAINMENU BEHAVIOR.. PUSH THE TEMPLATE NODE and ADD A MENUITEM HERE...
        if (ToolStrip is MenuStrip)
        {
            // The TemplateNode should no longer be selected.
            KeyboardHandlingService?.ResetActiveTemplateNodeSelectionState();

            try
            {
                ToolStripItem newItem = AddNewItem(typeof(ToolStripMenuItem));
                if (newItem is not null)
                {
                    if (_host.GetDesigner(newItem) is ToolStripItemDesigner newItemDesigner)
                    {
                        newItemDesigner._dummyItemAdded = true;
                        ((ToolStripMenuItemDesigner)newItemDesigner).InitializeDropDown();
                        try
                        {
                            _addingDummyItem = true;
                            newItemDesigner.ShowEditNode(clicked);
                        }
                        finally
                        {
                            _addingDummyItem = false;
                        }
                    }
                }
            }
            catch (InvalidOperationException ex)
            {
                Debug.Assert(NewItemTransaction is null, "NewItemTransaction should have been nulled out and cancelled by now.");
                GetService<IUIService>().ShowError(ex.Message);

                KeyboardHandlingService?.ResetActiveTemplateNodeSelectionState();
            }
        }
    }

    // Helper function to toggle the Item Visibility
    private void ShowHideToolStripItems(bool toolStripSelected)
    {
        // If we aren't Selected then turn the TOPLEVEL ITEMS visibility WYSIWYG
        foreach (ToolStripItem item in ToolStrip.Items)
        {
            if (item is DesignerToolStripControlHost)
            {
                continue;
            }

            // Get the itemDesigner...
            ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)_host.GetDesigner(item);
            itemDesigner?.SetItemVisible(toolStripSelected, this);
        }

        if (FireSyncSelection)
        {
            BehaviorService.SyncSelection();
            FireSyncSelection = false;
        }
    }

    // this is required when addition of TemplateNode causes the toolStrip to Layout .. E.g : Spring ToolStripStatusLabel.
    private void ToolStrip_LayoutCompleted(object sender, EventArgs e)
    {
        if (FireSyncSelection)
        {
            BehaviorService.SyncSelection();
        }
    }

    /// <summary>
    ///  Make sure the AddItem button stays in the right spot.
    /// </summary>
    private void ToolStrip_Resize(object sender, EventArgs e)
    {
        if (!_addingDummyItem && !_disposed && (CheckIfItemSelected() || SelectionService.GetComponentSelected(ToolStrip)))
        {
            if (_miniToolStrip is not null && _miniToolStrip.Visible)
            {
                LayoutToolStrip();
            }

            BehaviorService.SyncSelection();
        }
    }

    /// <summary>
    ///  Handle lower level mouse input.
    /// </summary>
    protected override void WndProc(ref Message m)
    {
        switch (m.MsgInternal)
        {
            case PInvokeCore.WM_CONTEXTMENU:
                if (GetHitTest(PARAM.ToPoint(m.LParamInternal)))
                {
                    return;
                }

                base.WndProc(ref m);
                break;
            case PInvokeCore.WM_LBUTTONDOWN:
            case PInvokeCore.WM_RBUTTONDOWN:
                // commit any InSitu if any...
                Commit();
                base.WndProc(ref m);
                break;
            default:
                base.WndProc(ref m);
                break;
        }
    }
}
